home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / dkbtrace / pbmplus / source / pbm / g3topbm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-10  |  6.7 KB  |  312 lines

  1. /* g3topbm.c - read a Group 3 FAX file and produce a portable bitmap
  2. **
  3. ** Copyright (C) 1989 by Paul Haeberli <paul@manray.sgi.com>.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include "pbm.h"
  14. #include "g3.h"
  15.  
  16. #define TABSIZE(tab) (sizeof(tab)/sizeof(struct tableentry))
  17. #define MAXCOLS 1728
  18. #define MAXROWS 4300    /* up to two pages long */
  19.  
  20. static int endoffile = 0;
  21. static int eols;
  22. static int rawzeros;
  23. static int shdata;
  24. static int kludge;
  25. static int reversebits;
  26. static int stretch;
  27.  
  28. #define WHASHA 3510
  29. #define WHASHB 1178
  30.  
  31. #define BHASHA 293
  32. #define BHASHB 2695
  33.  
  34. #define HASHSIZE 1021
  35. static tableentry* whash[HASHSIZE];
  36. static tableentry* bhash[HASHSIZE];
  37.  
  38. static void addtohash ARGS(( tableentry* hash[], tableentry* te, int n, int a, int b ));
  39. static tableentry* hashfind ARGS(( tableentry* hash[], int length, int code, int a, int b ));
  40. static int getfaxrow ARGS(( FILE* inf, int row, bit* bitrow ));
  41. static void skiptoeol ARGS(( FILE* file ));
  42. static int rawgetbit ARGS(( FILE* file ));
  43.  
  44. void
  45. main( argc, argv )
  46.     int argc;
  47.     char* argv[];
  48.     {
  49.     FILE* ifp;
  50.     int argn, rows, cols, row, col, i;
  51.     bit* bits[MAXROWS];
  52.     char* usage = "[-kludge][-reversebits][-stretch] [g3file]";
  53.  
  54.     pbm_init( &argc, argv );
  55.  
  56.     argn = 1;
  57.     kludge = 0;
  58.     reversebits = 0;
  59.     stretch = 0;
  60.  
  61.     /* Check for flags. */
  62.     while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  63.     {
  64.     if ( pm_keymatch( argv[argn], "-kludge", 2 ) )
  65.         kludge = 1;
  66.     else if ( pm_keymatch( argv[argn], "-reversebits", 2 ) )
  67.         reversebits = 1;
  68.     else if ( pm_keymatch( argv[argn], "-stretch", 2 ) )
  69.         stretch = 1;
  70.     else
  71.         pm_usage( usage );
  72.     argn++;
  73.     }
  74.  
  75.     if ( argn < argc )
  76.     {
  77.     ifp = pm_openr( argv[argn] );
  78.     argn++;
  79.     }
  80.     else
  81.     ifp = stdin;
  82.  
  83.     if ( argn != argc )
  84.     pm_usage( usage );
  85.  
  86.     eols = 0;
  87.  
  88.     if ( kludge )
  89.     {
  90.     /* Skip extra lines to get in sync. */
  91.     skiptoeol( ifp );
  92.     skiptoeol( ifp );
  93.     skiptoeol( ifp );
  94.     }
  95.     skiptoeol( ifp );
  96.     for ( i = 0; i < HASHSIZE; ++i )
  97.     whash[i] = bhash[i] = (tableentry*) 0;
  98.     addtohash( whash, twtable, TABSIZE(twtable), WHASHA, WHASHB );
  99.     addtohash( whash, mwtable, TABSIZE(mwtable), WHASHA, WHASHB );
  100.     addtohash( whash, extable, TABSIZE(extable), WHASHA, WHASHB );
  101.     addtohash( bhash, tbtable, TABSIZE(tbtable), BHASHA, BHASHB );
  102.     addtohash( bhash, mbtable, TABSIZE(mbtable), BHASHA, BHASHB );
  103.     addtohash( bhash, extable, TABSIZE(extable), BHASHA, BHASHB );
  104.  
  105.     cols = 0;
  106.     for ( rows = 0; rows < MAXROWS; ++rows )
  107.     {
  108.     bits[rows] = pbm_allocrow( MAXCOLS );
  109.     col = getfaxrow( ifp, rows, bits[rows] );
  110.     if ( endoffile )
  111.         break;
  112.     if ( col > cols )
  113.         cols = col;
  114.     if ( stretch )
  115.         {
  116.         bits[rows + 1] = bits[rows];
  117.         ++rows;
  118.         }
  119.     }
  120.  
  121.     pm_close( ifp );
  122.  
  123.     pbm_writepbminit( stdout, cols, rows, 0 );
  124.     for ( row = 0; row < rows; ++row )
  125.     pbm_writepbmrow( stdout, bits[row], cols, 0 );
  126.     pm_close( stdout );
  127.  
  128.     exit(0);
  129.     }
  130.  
  131. static void
  132. addtohash(hash, te, n, a, b)
  133.     tableentry* hash[];
  134.     tableentry* te;
  135.     int n, a, b;
  136. {
  137.     unsigned int pos;
  138.  
  139.     while (n--) {
  140.         pos = ((te->length+a)*(te->code+b))%HASHSIZE;
  141.         if (hash[pos] != 0)
  142.             pm_error( "internal error: addtohash fatal hash collision" );
  143.         hash[pos] = te;
  144.         te++;
  145.     }
  146. }
  147.  
  148. static tableentry*
  149. hashfind(hash, length, code, a, b)
  150.     tableentry* hash[];
  151.     int length, code;
  152.     int a, b;
  153.     {
  154.     unsigned int pos;
  155.     tableentry* te;
  156.  
  157.     pos = ((length+a)*(code+b))%HASHSIZE;
  158.     if (pos < 0 || pos >= HASHSIZE)
  159.     pm_error(
  160.         "internal error: bad hash position, length %d code %d pos %d",
  161.         length, code, pos );
  162.     te = hash[pos];
  163.     return ((te && te->length == length && te->code == code) ? te : 0);
  164.     }
  165.  
  166. static int
  167. getfaxrow( inf, row, bitrow )
  168.     FILE* inf;
  169.     int row;
  170.     bit* bitrow;
  171. {
  172.     int col;
  173.     bit* bP;
  174.     int curlen, curcode, nextbit;
  175.     int count, color;
  176.     tableentry* te;
  177.  
  178.     for ( col = 0, bP = bitrow; col < MAXCOLS; ++col, ++bP )
  179.         *bP = PBM_WHITE;
  180.     col = 0;
  181.     rawzeros = 0;
  182.     curlen = 0;
  183.     curcode = 0;
  184.     color = 1;
  185.     count = 0;
  186.     while (!endoffile) {
  187.         if (col >= MAXCOLS) {
  188.             skiptoeol(inf);
  189.             return (col); 
  190.         }
  191.         do {
  192.             if (rawzeros >= 11) {
  193.                 nextbit = rawgetbit(inf);
  194.                 if (nextbit) {
  195.                     if (col == 0)
  196.                         /* XXX should be 6 */
  197.                         endoffile = (++eols == 3);
  198.                     else
  199.                         eols = 0;
  200. #ifdef notdef
  201.                     if (col && col < 1728)
  202.                         pm_message(
  203.                            "warning, row %d short (len %d)",
  204.                             row, col );
  205. #endif /*notdef*/
  206.                     return (col); 
  207.                 }
  208.             } else
  209.                 nextbit = rawgetbit(inf);
  210.             curcode = (curcode<<1) + nextbit;
  211.             curlen++;
  212.         } while (curcode <= 0);
  213.         if (curlen > 13) {
  214.             pm_message(
  215.       "bad code word at row %d, col %d (len %d code 0x%x), skipping to EOL",
  216.                 row, col, curlen, curcode, 0 );
  217.             skiptoeol(inf);
  218.             return (col);
  219.         }
  220.         if (color) {
  221.             if (curlen < 4)
  222.                 continue;
  223.             te = hashfind(whash, curlen, curcode, WHASHA, WHASHB);
  224.         } else {
  225.             if (curlen < 2)
  226.                 continue;
  227.             te = hashfind(bhash, curlen, curcode, BHASHA, BHASHB);
  228.         }
  229.         if (!te)
  230.             continue;
  231.         switch (te->tabid) {
  232.         case TWTABLE:
  233.         case TBTABLE:
  234.             count += te->count;
  235.             if (col+count > MAXCOLS) 
  236.                 count = MAXCOLS-col;
  237.             if (count > 0) {
  238.                 if (color) {
  239.                     col += count;
  240.                     count = 0;
  241.                 } else {
  242.                     for ( ; count > 0; --count, ++col )
  243.                         bitrow[col] = PBM_BLACK;
  244.                 }
  245.             }
  246.             curcode = 0;
  247.             curlen = 0;
  248.             color = !color;
  249.             break;
  250.         case MWTABLE:
  251.         case MBTABLE:
  252.             count += te->count;
  253.             curcode = 0;
  254.             curlen = 0;
  255.             break;
  256.         case EXTABLE:
  257.             count += te->count;
  258.             curcode = 0;
  259.             curlen = 0;
  260.             break;
  261.         default:
  262.             pm_error( "internal bad poop" );
  263.         }
  264.     }
  265.     return (0);
  266. }
  267.  
  268. static void
  269. skiptoeol( file )
  270.     FILE* file;
  271.     {
  272.     while ( rawzeros < 11 )
  273.     (void) rawgetbit( file );
  274.     for ( ; ; )
  275.     {
  276.     if ( rawgetbit( file ) )
  277.         break;
  278.     }
  279.     }
  280.  
  281. static int shbit = 0;
  282.  
  283. static int
  284. rawgetbit( file )
  285.     FILE* file;
  286.     {
  287.     int b;
  288.  
  289.     if ( ( shbit & 0xff ) == 0 )
  290.     {
  291.     shdata = getc( file );
  292.     if ( shdata == EOF )
  293.         pm_error( "EOF / read error at line %d", eols );
  294.     shbit = reversebits ? 0x01 : 0x80;
  295.     }
  296.     if ( shdata & shbit )
  297.     {
  298.     rawzeros = 0;
  299.     b = 1;
  300.     }
  301.     else
  302.     {
  303.     rawzeros++;
  304.     b = 0;
  305.     }
  306.     if ( reversebits )
  307.     shbit <<= 1;
  308.     else
  309.     shbit >>= 1;
  310.     return b;
  311.     }
  312.